
#ifndef __PAISLEYPARK__RESTRICTIONOPERATORFACTORY_H__
#define __PAISLEYPARK__RESTRICTIONOPERATORFACTORY_H__

#include "RestrictionOperator.h"
#include <map>
#include <cstring>

template <size_t DIM>
class RestrictionOperatorFactory {
public:
	typedef RestrictionOperator<DIM>* (*CreateRestrictionOperatorCallback)();
private:
	typedef std::map<std::string, CreateRestrictionOperatorCallback> CallbackMp;
public:

	bool RegisterOperator(const std::string _OperatorId, CreateRestrictionOperatorCallback _createFn);

	bool UnregisterOperator(const std::string _OperatorId);

	RestrictionOperator<DIM>* CreateOperator(const std::string _OperatorId);

	~RestrictionOperatorFactory(){};

	static RestrictionOperatorFactory<DIM>* Instance() {
		if(!__obj) {
			__obj = new RestrictionOperatorFactory<DIM>;
		}
		return __obj;
	}
private:
	static RestrictionOperatorFactory<DIM>* __obj;

	CallbackMp __callbacks;

	RestrictionOperatorFactory(){};
};

template <size_t DIM>
RestrictionOperatorFactory<DIM>* RestrictionOperatorFactory<DIM>::__obj = 0;

template <size_t DIM>
bool RestrictionOperatorFactory<DIM>::RegisterOperator(const std::string _OperatorId,
														  CreateRestrictionOperatorCallback _createFn) {
	return __callbacks.insert(typename CallbackMp::value_type(_OperatorId, _createFn)).second;
};

template <size_t DIM>
bool RestrictionOperatorFactory<DIM>::UnregisterOperator(const std::string _OperatorId) {
	return __callbacks.erase(_OperatorId) == 1;
};

template <size_t DIM>
RestrictionOperator<DIM>* RestrictionOperatorFactory<DIM>::CreateOperator(const std::string _OperatorId) {
	typename CallbackMp::const_iterator i = __callbacks.find(_OperatorId);
	if(i == __callbacks.end()) {
		std::cerr << "Unknown Operator Id." << std::endl;
		std::exit(-1);
	}
	return (i->second)();
};

#else
//Do nothing.
#endif
